package com.hnchances.studentscoresystem.util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT工具类
 * 功能：生成Token、解析Token、校验Token有效性
 * 对应文档需求：3.4.4用户登录（生成JWT Token）、3.4.5用户信息查询（解析Token）
 */
@Slf4j
@Component
public class JwtUtil {

    /**
     * JWT密钥（从配置文件读取，生产环境需加密存储）
     */
    @Value("${jwt.secret}")
    private String jwtSecret;

    /**
     * Token有效期（毫秒，默认24小时，从配置文件读取）
     */
    @Value("${jwt.expiration}")
    private Long jwtExpiration;

    /**
     * 生成JWT Token（包含用户核心身份信息）
     * @param userId 用户ID（关联user表id）
     * @param userName 用户名（关联user表userName）
     * @param identity 用户身份（0-学生，1-老师，2-管理员，关联user表identity）
     * @return JWT Token字符串
     */
    public String generateToken(Long userId, String userName, Integer identity) {
        // 1. 构建Token载荷（存储用户核心信息，避免敏感数据）
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", userId);
        claims.put("userName", userName);
        claims.put("identity", identity);

        // 2. 生成密钥（基于配置的secret，适配JWT HS512算法）
        SecretKey secretKey = Keys.hmacShaKeyFor(jwtSecret.getBytes(StandardCharsets.UTF_8));

        // 3. 构建并生成Token
        return Jwts.builder()
                .setClaims(claims) // 设置载荷
                .setExpiration(new Date(System.currentTimeMillis() + jwtExpiration)) // 设置过期时间
                .signWith(secretKey, SignatureAlgorithm.HS512) // 签名算法与密钥
                .compact();
    }

    /**
     * 解析JWT Token，获取完整载荷（Claims）
     * @param token JWT Token字符串
     * @return Claims对象（包含用户ID、用户名、身份等信息）
     * @throws RuntimeException Token无效或过期时抛出
     */
    public Claims parseToken(String token) {
        try {
            SecretKey secretKey = Keys.hmacShaKeyFor(jwtSecret.getBytes(StandardCharsets.UTF_8));
            return Jwts.parserBuilder()
                    .setSigningKey(secretKey) // 设置验签密钥
                    .build()
                    .parseClaimsJws(token) // 解析Token
                    .getBody(); // 获取载荷
        } catch (Exception e) {
            log.error("JWT Token解析失败，token: {}, 异常信息: {}", token.substring(0, 10) + "...", e.getMessage());
            throw new RuntimeException("Token无效或已过期，请重新登录");
        }
    }

    /**
     * 从Token中提取用户ID
     * @param token JWT Token字符串
     * @return 用户ID（Long类型，关联user表id）
     */
    public Long getUserIdFromToken(String token) {
        Claims claims = parseToken(token);
        return claims.get("userId", Long.class);
    }

    /**
     * 从Token中提取用户身份
     * @param token JWT Token字符串
     * @return 用户身份（0-学生，1-老师，2-管理员，关联user表identity）
     */
    public Integer getIdentityFromToken(String token) {
        Claims claims = parseToken(token);
        return claims.get("identity", Integer.class);
    }

    /**
     * 校验Token是否已过期
     * @param token JWT Token字符串
     * @return true-已过期，false-未过期
     */
    public boolean isTokenExpired(String token) {
        Claims claims = parseToken(token);
        Date expirationDate = claims.getExpiration();
        // 比较Token过期时间与当前时间
        return expirationDate.before(new Date());
    }
}